package com.jdwx.opengl.face.dface.activity;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MenuItem;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.dface.api.FaceDetect;
import com.dface.api.FacePose;
import com.dface.api.FaceRecognize;
import com.dface.api.FaceTool;
import com.dface.dto.AccuracyMode;
import com.dface.dto.Bbox;
import com.dface.dto.DetectMode;
import com.dface.dto.FaceLandmark;
import com.dface.exception.DFaceException;
import com.jdwx.opengl.R;
import com.jdwx.opengl.face.dface.DFaceApplication;
import com.jdwx.opengl.face.dface.views.FaceOverlayView;
import com.jdwx.opengl.face.utils.CameraHelper;
import com.jdwx.opengl.face.utils.CameraListener;
import com.jdwx.opengl.face.utils.DFaceSetting;
import com.jdwx.opengl.face.utils.FaceResult;
import com.jdwx.opengl.face.utils.NV21ToBitmap;

import java.io.File;
import java.util.ArrayList;
import java.util.List;


public class FaceRegisterActivity extends AppCompatActivity {

    //region private
    private static final String TAG = "FacePhotoActivity";
    private CameraHelper cameraHelper;
    private Camera.Size previewSize;
    private static final int ACTION_REQUEST_PERMISSIONS = 0x001;

    private NV21ToBitmap yuvConvert = null;
    int MAX_FACE_COUNT = 1;

    //检测到的人脸(人脸边框渲染数据缓存)
    //private FaceResult drawFaceBuffer[];

//    private FaceDetect faceDetect = new FaceDetect();
//    private FacePose facePose = new FacePose();
//    private FaceRecognize faceRecognize = new FaceRecognize();
//    private FaceTool faceTool = new FaceTool();

    int skipFrameCount = 0;
    boolean finishJob = false;
    float YAW_THRESHOLD = 25.0f;
    float PITCH_THRESHOLD = 25.0f;
    float ROW_THRESHOLD = 25.0f;

    SurfaceView surface_view;
    FaceOverlayView face_overlay_view;
    private String appInnerCacheDir;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_chevron_left_primary);
        getSupportActionBar().setTitle( "采集人脸" );
        //requestWindowFeature(Window.FEATURE_NO_TITLE);//这行代码一定要在setContentView之前，不然会闪退
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_face_register);

        init();
        initEngine();
    }

    @SuppressLint("SourceLockedOrientationActivity")
    void init(){
        //保持亮屏
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        //权限申请
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams attributes = getWindow().getAttributes();
            attributes.systemUiVisibility = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
            getWindow().setAttributes(attributes);
        }

        // Activity启动后就锁定为启动时的方向
        switch (getResources().getConfiguration().orientation) {
            case Configuration.ORIENTATION_PORTRAIT:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                break;
            case Configuration.ORIENTATION_LANDSCAPE:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                break;
            default:
                break;
        }

        face_overlay_view= findViewById(R.id.face_overlay_view);
        surface_view= findViewById(R.id.surface_view);

        //在布局结束后才做初始化操作
        surface_view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                surface_view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                initCamera();
            }

        });

        yuvConvert = new NV21ToBitmap(this);
//        drawFaceBuffer = new FaceResult[MAX_FACE_COUNT];
//        for (int i = 0; i < MAX_FACE_COUNT; i++) {
//            drawFaceBuffer[i] = new FaceResult();
//        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                finish();
                return false;
        }
        return super.onOptionsItemSelected(item);
    }

    void submit(String strFeature) {
        cameraHelper.stop();
        cameraHelper.release();
        Intent intent = new Intent();
        intent.putExtra("feature", strFeature);
        setResult(RESULT_OK, intent);
        finish();
    }

    @Override
    protected void onDestroy() {
        if (cameraHelper != null) {
            cameraHelper.release();
            cameraHelper = null;
        }
        unInitEngine();
        super.onDestroy();
    }

    @Override
    protected void onStop() {
        unInitEngine();
        super.onStop();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == ACTION_REQUEST_PERMISSIONS) {
            boolean isAllGranted = true;
            for (int grantResult : grantResults) {
                isAllGranted &= (grantResult == PackageManager.PERMISSION_GRANTED);
            }
            if (isAllGranted) {
                initEngine();
                initCamera();
                if (cameraHelper != null) {
                    cameraHelper.start();
                }
            } else {
                Toast.makeText(this, "permission denied!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    //endregion

    //region DFace Engine

    /**
     * 初始化引擎
     */
    private void initEngine() {
        String modelPath = getModelPath();
        try {
            //初始化人脸检测
           // faceDetect.initLoad(modelPath);
           // facePose.initLoad(modelPath);
           // faceRecognize.initLoad(modelPath, AccuracyMode.PROFILE.getMode());
        } catch (DFaceException dfex) {
            int err_code = dfex.getCode();
            String err_msg = dfex.getMessage();
            Log.e(TAG, "DFaceException Error Code:" + err_code);
            Log.e(TAG, "DFaceException Error MSG:" + err_msg);
        }
    }

    /**
     * 销毁引擎
     */
    private void unInitEngine() {
//        faceDetect.uninitLoad();
//        facePose.uninitLoad();
//        faceRecognize.uninitLoad();
    }

    /**
     * 获得模型目录
     *
     * @return
     */
    private String getModelPath() {
        appInnerCacheDir = DFaceApplication.ins().getCacheDir().getAbsolutePath();
        String root = getCacheFilePath();
        //File sdDir = Environment.getExternalStorageDirectory();//获取SD卡根目录
        String modelPath = root + "/dface/normal_binary/";
        if( !new File( modelPath ).exists() ){
            new File( modelPath ).mkdirs();
        }
        return modelPath;
    }
    public  String getCacheFilePath() {
        String root;
        if (hasSDCard())
            root = Environment.getExternalStorageDirectory()  + "/fileCache";
        else
            root = appInnerCacheDir + "/fileCache";
        return root;
    }
    public static boolean hasSDCard() {
        String status = Environment.getExternalStorageState();
        if (status.equals(Environment.MEDIA_MOUNTED)) {
            return true;
        } else {
            return false;
        }
    }

    //endregion

    //region common

    /**
     * 清空之前检测到的人脸数据
     */
    private void clearDrawFaceBuffer() {
        //之前检测到的人脸数据清空一遍
//        for (int j = 0; j < drawFaceBuffer.length; j++) {
//            if (drawFaceBuffer[j] != null) {
//                drawFaceBuffer[j].clear();
//            }
//        }
    }

    /**
     * 刷新显示框
     *
     * @param faceResults
     */
    private void freshDisplayDrawFaceBoxs(FaceResult[] faceResults) {
        //send face to FaceView to draw rect
        face_overlay_view.setFaces(faceResults);
    }

    /**
     * 初始化相机
     */
    private void initCamera() {
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);

        CameraListener cameraListener = new CameraListener() {
            @Override
            public void onCameraOpened(Camera camera, int cameraId, int displayOrientation, boolean isMirror) {
                previewSize = camera.getParameters().getPreviewSize();

                Camera.CameraInfo info = new Camera.CameraInfo();
                Camera.getCameraInfo(cameraId, info);
                if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    face_overlay_view.setFront(true);
                } else {
                    face_overlay_view.setFront(false);
                }
                face_overlay_view.setDisplayOrientation(displayOrientation);
                if (displayOrientation == 90 || displayOrientation == 270) {
                    face_overlay_view.setPreviewSize(previewSize.height, previewSize.width);
                } else {
                    face_overlay_view.setPreviewSize(previewSize.width, previewSize.height);
                }
            }

            @Override
            public void onPreview(final byte[] nv21, Camera camera, int cameraRotation) {
                try {
                    //跳过前20帧, 摄像头刚启动时，画面比较暗
                    if (skipFrameCount++ < 20 || finishJob) {
                        return;
                    }
                    int cameraPreviewWidth = camera.getParameters().getPreviewSize().width;
                    int cameraPreviewHeight = camera.getParameters().getPreviewSize().height;
                    Bitmap frameBitmap = yuvConvert.nv21ToBitmap(nv21, cameraPreviewWidth, cameraPreviewHeight);

                   // faceDetect.SetWorkMode(DetectMode.Precision_Low.getMode());
                    //设置最小人脸
                   // faceDetect.SetMinSize(DFaceApplication.faceConfig.DETECT_MIN_SIZE);
                    //设置线程数量
                   // faceDetect.SetNumThreads(1);

                    //旋转图像数据为正方向(android画面需要旋转90度或者270度),注意返回的是RGB格式
                  //  final Bitmap frameRotatedBitmap = faceTool.rotateBitmap(frameBitmap, cameraRotation);

                    //检测人脸(检测图像缩放后的人脸)
                   // List<Bbox> faceBboxs = faceDetect.detectionMax(frameRotatedBitmap, true);
/*
                    if (faceBboxs == null || faceBboxs.isEmpty()) {
                        freshDisplayDrawFaceBoxs(drawFaceBuffer);
                        return;
                    }

                    clearDrawFaceBuffer();

                    final Bbox faceItem = faceBboxs.get(0);

                    //原图(相机预览图)尺寸下的人脸
                    drawFaceBuffer[0].setFace(0, faceItem.score, faceItem.x, faceItem.y, faceItem.width, faceItem.height, faceItem.getPoint(), System.currentTimeMillis(), "", Color.GREEN);

                    freshDisplayDrawFaceBoxs(drawFaceBuffer);

                    List<Bbox> predictInput = new ArrayList<>();
                    predictInput.add(faceItem);
//                                判断人脸清晰度
//                                double[] blur = facePose.predictBlur(frameRotatedBitmap, predictInput);
//                                if (blur.length == 0 || blur[0] < 600) {
//                                    return;
//                                }
                    //判断人脸光照质量
                    int[] light = facePose.predictLight(frameRotatedBitmap, predictInput);
                    if (light.length == 0 || light[0] == 1 || light[0] == 2) {
                        return;
                    }

                    List<FaceLandmark> poses = facePose.predictPose(frameRotatedBitmap, predictInput);
                    double[] yprxyz = poses.get(0).getPose3D();
                    //姿态角度
                    double yaw = Math.abs(yprxyz[0]);
                    double pitch = Math.abs(yprxyz[1]);
                    double row = Math.abs(yprxyz[2]);

                    //只允许正脸注册(判断人脸的角度和相机偏离距离)
                    if (yaw < YAW_THRESHOLD && pitch < PITCH_THRESHOLD && row < ROW_THRESHOLD) {
                        finishJob = true;

                        //提取人脸特征
                        byte[] feature = faceRecognize.extractFaceFeatureByImg(frameRotatedBitmap, faceItem);
                        //判断是否返回为空特征
                        if (feature == null || feature.length == 0) {
                            return;
                        }

                        String strFeature = new String(Base64.encode(feature, Base64.DEFAULT));
                        //裁剪并旋转为正方向人脸
                        DFaceSetting.getInstance().tmpBitmap = faceTool.cropBitmap(frameRotatedBitmap, faceItem.getX(), faceItem.getY(), faceItem.getWidth(), faceItem.getHeight());
                        DFaceSetting.getInstance().tmpBitmap = DFaceSetting.getInstance().CompressImage(DFaceSetting.getInstance().tmpBitmap);
                        submit(strFeature);
                    }
                    */

                } catch (Exception e) {
                }
            }

            @Override
            public void onCameraClosed() {
                Log.i(TAG, "onCameraClosed: ");
            }

            @Override
            public void onCameraError(Exception e) {
                Log.i(TAG, "onCameraError: " + e.getMessage());
            }

            @Override
            public void onCameraConfigurationChanged(int cameraID, int displayOrientation) {

                Log.i(TAG, "onCameraConfigurationChanged: " + cameraID + "  " + displayOrientation);
            }
        };

        //获取屏幕方向
        int ScreenRotation = getWindowManager().getDefaultDisplay().getRotation();
        int cameraOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;

        switch (ScreenRotation) {
            case Surface.ROTATION_0:
            case Surface.ROTATION_180:
                cameraOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                break;
            case Surface.ROTATION_90:
            case Surface.ROTATION_270:
                cameraOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                break;
        }
        cameraHelper = new CameraHelper.Builder()
                .previewViewSize(new Point( DFaceApplication.faceConfig.CAMERA_WIDTH, DFaceApplication.faceConfig.CAMERA_HEIGHT))
                .rotation(cameraOrientation)
                .specificCameraId( DFaceApplication.faceConfig.COLOR_CAMERAID)
                .isMirror( DFaceApplication.faceConfig.CAMERA_IS_MIRROW)
                .additionalRotation( DFaceApplication.faceConfig.CAMERA_ADDITIONAL_ROTATE)
                .previewOn(surface_view)
                .viewSize(getResources().getDisplayMetrics().heightPixels,getResources().getDisplayMetrics().widthPixels)
                .cameraListener(cameraListener)
                .build();
        cameraHelper.init();
    }
    //endregion
}
